home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Selectorama.c
-
- Copyright 1996, Adobe Systems Incorporated. All rights reserved.
-
- */
-
- #if __MWERKS__
- #include <SetupA4.h> // A4-globals
- #include <A4Stuff.h> // A4-globals
- #endif
-
- #if defined(THINK_C) || defined(__MWERKS__)
- #define ENTRYPOINT main
- #endif
-
- #include "Selectorama.h"
-
- Handle hDllInstance = NULL;
-
- /*****************************************************************************/
-
- void InitGlobals (GPtr globals);
- void TrimVRect (VRect *dst, VRect *src);
- static Boolean EqualVRects (VRect *a, VRect *b);
- static int32 AccountChannel (ReadChannelDesc *source,
- ReadChannelDesc *mask,
- WriteChannelDesc *dest);
- static void ApplyChannel (GPtr globals, ReadChannelDesc *source, PixelMemoryDesc *sDesc,
- ReadChannelDesc *mask, PixelMemoryDesc *mDesc,
- WriteChannelDesc *dest, ChannelReadPort destRead,
- PixelMemoryDesc *dDesc, PixelMemoryDesc *rDesc,
- int32 *done, int32 total);
- void DoExecute (GPtr globals);
-
- /*****************************************************************************/
-
- /* All calls to the plug-in module come through this routine. It must be
- placed first in the resource. To achieve this, most development systems
- require that this be the first routine in the source. */
-
- #if MSWindows
- void ENTRYPOINT (short selector,
- PISelectionParams *selectionParamBlock,
- long *data,
- short *result)
- #else
- pascal void ENTRYPOINT (short selector,
- PISelectionParams *selectionParamBlock,
- long *data,
- short *result)
- #endif
- {
-
- Globals globalValues;
- GPtr globals = &globalValues;
-
- #if __MWERKS__
- EnterCodeResource(); // A4-globals
- #endif
-
- if (!*data)
- {
-
- InitGlobals (globals);
-
- *data = (long) NewHandle (sizeof (Globals));
-
- if (!*data)
- {
- *result = memFullErr;
- return;
- }
-
- ** (GHdl) *data = globalValues;
-
- }
-
- globalValues = ** (GHdl) *data;
-
- gStuff = selectionParamBlock;
- gResult = noErr;
-
- switch (selector)
- {
-
- case selectionSelectorAbout:
- DoAbout (globals);
- break;
-
- case selectionSelectorExecute:
- DoExecute (globals);
- break;
-
- default:
- gResult = selectionBadParameters;
- }
-
- *result = gResult;
- ** (GHdl) *data = globalValues;
-
- #if __MWERKS__
- ExitCodeResource(); // A4-globals
- #endif
- }
-
- /*****************************************************************************/
-
- void InitGlobals (GPtr globals)
- {
-
- gWhatArea = iSelectMin;
- gWhatChannels = iUseTarget;
- gPercent = 50;
- gCreate = iCreateSelection;
- gQueryForParameters = false;
-
- }
-
- /*****************************************************************************/
-
- static void TrimVRect (VRect *dst, VRect *src)
- {
-
- if (dst->top < src->top ) dst->top = src->top;
- if (dst->left < src->left ) dst->left = src->left;
- if (dst->bottom > src->bottom) dst->bottom = src->bottom;
- if (dst->right > src->right ) dst->right = src->right;
-
- }
-
- /*****************************************************************************/
-
- static Boolean EqualVRects (VRect *a, VRect *b)
- {
-
- return a->top == b->top
- && a->left == b->left
- && a->bottom == b->bottom
- && a->right == b->right;
-
- }
-
- /*****************************************************************************/
-
- static int32 AccountChannel (ReadChannelDesc *source,
- ReadChannelDesc *mask,
- WriteChannelDesc *dest)
- {
-
- VRect limit;
-
- limit = source->bounds;
- TrimVRect (&limit, &dest->bounds);
- if (mask != NULL) TrimVRect (&limit, &mask->bounds);
-
- if (limit.right <= limit.left || limit.bottom <= limit.top) return 0;
-
- return (limit.right - limit.left) * (limit.bottom - limit.top);
-
- }
-
- /*****************************************************************************/
-
- static void ApplyChannel (GPtr globals,
- ReadChannelDesc *source,
- PixelMemoryDesc *sDesc,
- ReadChannelDesc *mask,
- PixelMemoryDesc *mDesc,
- WriteChannelDesc *dest,
- ChannelReadPort destRead,
- PixelMemoryDesc *dDesc,
- PixelMemoryDesc *rDesc,
- int32 *done,
- int32 total)
- {
-
- VRect limit;
- int32 row, col, row2, col2;
- unsigned8 *s, *m, *d;
- unsigned8 *r = (unsigned8 *)rDesc->data;
- Boolean initRandom = (*r == kInitRandom);
-
- limit = source->bounds;
- TrimVRect (&limit, &dest->bounds);
- if (mask != NULL) TrimVRect (&limit, &mask->bounds);
-
- if (limit.right <= limit.left || limit.bottom <= limit.top) return;
-
- for (row = limit.top; row < limit.bottom; row += kBlockRows)
- for (col = limit.left; col < limit.right; col += kBlockCols)
- {
-
- VRect area;
- PSScaling scaling;
- VRect wrote;
-
- if (TestAbort ())
- {
- gResult = userCanceledErr;
- return;
- }
-
- area.top = row; area.bottom = row + kBlockRows;
- area.left = col; area.right = col + kBlockCols;
-
- if (limit.bottom < area.bottom) area.bottom = limit.bottom;
- if (limit.right < area.right ) area.right = limit.right;
-
- scaling.sourceRect = area;
- scaling.destinationRect = area;
-
- gResult = ReadPixels (destRead, &scaling, &area, dDesc, &wrote);
- if (gResult != noErr) return;
-
- if (!EqualVRects (&area, &wrote))
- {
- gResult = -1;
- return;
- }
-
- gResult = ReadPixels (source->port, &scaling, &area, sDesc, &wrote);
- if (gResult != noErr) return;
-
- if (!EqualVRects (&area, &wrote))
- {
- gResult = -1;
- return;
- }
-
- if (mask != NULL)
- {
-
- gResult = ReadPixels (mask->port, &scaling, &area, mDesc, &wrote);
- if (gResult != noErr) return;
-
- if (!EqualVRects (&area, &wrote))
- {
- gResult = -1;
- return;
- }
- }
- m = (unsigned8 *) mDesc->data;
- /* mask all set and ready to go */
-
- /* heart of the routine. Compares source pixel and destination
- pixel and, if destination is smaller, replaces it with
- source */
-
- s = (unsigned8 *) sDesc->data;
- d = (unsigned8 *) dDesc->data;
- r = (unsigned8 *) rDesc->data;
-
- for (row2 = kBlockRows; row2 > 0; --row2)
- for (col2 = kBlockCols; col2 > 0; --col2)
- {
-
- switch (gWhatArea)
- {
- case iSelectMin:
- if (mask != NULL && *m < *s ) *s = *m;
- if (*s > 127) *d = *s;
- else *d = 0;
- break;
- case iSelectMax:
- if (mask != NULL && *m < *s ) *s = *m;
- if (*s < 128) *d = 255 - *s; // if (*d < *s) *d = *s;
- else *d = 0;
- break;
- case iSelectRandom:
- if (initRandom)
- {
- if ((((unsigned16) Random ()) % 100) < gPercent)
- *r = kRandomOn; // flag as picked
- else *r = kRandomOff; // flag as off
- }
- if (*r == kRandomOn)
- *d = 255;
- else *d = 0;
- break;
- }
- ++s;
- ++d;
- ++r;
- if (mask != NULL) ++m;
- }
-
- gResult = WritePixels (dest->port, &area, dDesc);
- if (gResult != noErr) return;
-
- *done += (area.right - area.left) * (area.bottom - area.top);
-
- UpdateProgress (*done, total);
-
- }
-
- }
-
- /*****************************************************************************/
-
- void DoExecute (GPtr globals)
- {
-
- int32 total = 0;
- int32 done = 0;
- Ptr p = 0;
-
- Boolean doThis = true;
-
- BufferID sBuffer = 0;
- Ptr sData = NULL;
- BufferID dBuffer = 0;
- Ptr dData = NULL;
- BufferID mBuffer = 0;
- Ptr mData = NULL;
- BufferID rBuffer = 0;
- Ptr rData = NULL;
-
- PixelMemoryDesc sDesc, dDesc, mDesc, rDesc;
-
- ReadImageDocumentDesc *doc = gStuff->documentInfo;
- WriteChannelDesc *selection = gStuff->newSelection;
- ChannelReadPort selectionRead;
- ReadChannelDesc *composite;
- ReadChannelDesc *transparency;
- ReadChannelDesc *curChannel;
-
-
- /* Access the port procs. */
-
- if (!WarnChannelPortAvailable ())
- {
- gResult = errPlugInHostInsufficient;
- goto CleanUp;
- }
-
- gQueryForParameters = ReadScriptParams (globals);
-
- if ( gQueryForParameters ) doThis = DoParameters (globals);
-
- if ( !doThis ) goto CleanUp; // user cancelled, etc.
-
- /* look in gStuff->supportedTreatments for support for this next thang */
-
- if (gCreate == iCreateMaskpath)
- { // can't do that!
- p = PIGetResource (StringResource, errCantCreatePath, &total);
- if (p)
- {
- gResult = PIReportError((unsigned char *)p);
- PIReleaseResource(p);
- }
- else gStuff->treatment = KeyToEnum(EnumToKey(gCreate,typeCreate),typePISel);
- // otherwise Pshop will catch it automatically
- goto CleanUp;
- }
- else
- gStuff->treatment = KeyToEnum(EnumToKey(gCreate,typeCreate),typePISel);
- // got it. Move on.
-
- /* We will need a read port for the selection. */
-
- gResult = ReadFromWritePort(&selectionRead, selection->port);
- if (gResult != noErr) goto CleanUp;
-
- /* Figure out which composite data to use. */
-
- if (DoTarget)
- {
- composite = doc->targetCompositeChannels;
- transparency = doc->targetTransparency;
-
- if (composite == NULL)
- {
- composite = doc->mergedCompositeChannels;
- transparency = doc->mergedTransparency;
- }
- }
- else
- {
- composite = doc->mergedCompositeChannels;
- transparency = doc->mergedTransparency;
- }
-
- /* Allocate the buffers. */
-
- if (!WarnBufferProcsAvailable ())
- {
- gResult = +1;
- goto CleanUp;
- }
-
- #define kBufferSize kBlockRows * (long) kBlockCols
-
- gResult = AllocateBuffer (kBufferSize, &sBuffer);
- if (gResult != noErr) goto CleanUp;
-
- gResult = AllocateBuffer (kBufferSize, &dBuffer);
- if (gResult != noErr) goto CleanUp;
-
- gResult = AllocateBuffer (kBufferSize, &rBuffer);
- if (gResult != noErr) goto CleanUp;
-
- if (transparency != NULL)
- {
- gResult = AllocateBuffer (kBufferSize, &mBuffer);
- if (gResult != noErr) goto CleanUp;
- }
-
- /* Lock the buffers down. */
-
- sData = LockBuffer (sBuffer, false);
- dData = LockBuffer (dBuffer, false);
- rData = LockBuffer (rBuffer, false);
- if (mBuffer != 0) mData = LockBuffer (mBuffer, false);
-
- /* Set up the pixel memory descriptors. */
-
- sDesc.data = sData;
- sDesc.rowBits = kBlockCols * 8;
- sDesc.colBits = 8;
- sDesc.bitOffset = 0;
- sDesc.depth = 8;
-
- dDesc = sDesc;
- dDesc.data = dData;
-
- rDesc = sDesc;
- rDesc.data = rData;
-
- mDesc = sDesc;
- mDesc.data = mData;
-
- rData[0] = kInitRandom; // flag for uninitialized random buffer
-
- /* Count the channels to process. */
-
- if (doc->selection != NULL)
- total += AccountChannel (doc->selection, NULL, selection);
-
- curChannel = composite;
- while (curChannel != NULL)
- {
- if (DoTarget ? curChannel->target : curChannel->shown)
- total += AccountChannel (curChannel, transparency, selection);
-
- curChannel = curChannel->next;
- }
-
-
- if (doc->targetLayerMask != NULL &&
- (DoTarget ? doc->targetLayerMask->target : doc->targetLayerMask->shown))
- total += AccountChannel (doc->targetLayerMask, NULL, selection);
-
- curChannel = doc->alphaChannels;
- while (curChannel != NULL)
- {
- if (DoTarget ? curChannel->target : curChannel->shown)
- total += AccountChannel (curChannel, NULL, selection);
-
- curChannel = curChannel->next;
- }
-
-
- /* Apply any existing selection. */
-
- if (doc->selection != NULL)
- {
- ApplyChannel (globals, doc->selection, &sDesc,
- NULL, &mDesc,
- selection, selectionRead, &dDesc,
- &rDesc, &done, total);
- if (gResult != noErr) goto CleanUp;
- }
-
- /* Apply each of the channels. This isn't the most efficient
- approach since it reads the data back out of the selection
- repeatedly, but it provides a good work out for the code. */
-
- curChannel = composite;
- while (curChannel != NULL)
- {
- if (DoTarget ? curChannel->target : curChannel->shown)
- {
- ApplyChannel (globals, curChannel, &sDesc,
- transparency, &mDesc,
- selection, selectionRead, &dDesc,
- &rDesc, &done, total);
- if (gResult != noErr) goto CleanUp;
- }
-
- curChannel = curChannel->next;
- }
-
- /* Apply the layer mask. */
- if (doc->targetLayerMask != NULL &&
- (DoTarget ? doc->targetLayerMask->target : doc->targetLayerMask->shown))
- {
- ApplyChannel (globals, doc->targetLayerMask, &sDesc,
- NULL, &mDesc,
- selection, selectionRead, &dDesc,
- &rDesc, &done, total);
- if (gResult != noErr) goto CleanUp;
- }
-
- /* Process the alpha channels. */
- curChannel = doc->alphaChannels;
- while (curChannel != NULL)
- {
- if (DoTarget ? curChannel->target : curChannel->shown)
- {
- ApplyChannel (globals, curChannel, &sDesc,
- NULL, &mDesc,
- selection, selectionRead, &dDesc,
- &rDesc, &done, total);
- if (gResult != noErr) goto CleanUp;
- }
-
- curChannel = curChannel->next;
- }
-
- CleanUp:
-
- if (sData != NULL) UnlockBuffer (sBuffer);
- if (dData != NULL) UnlockBuffer (dBuffer);
- if (mData != NULL) UnlockBuffer (mBuffer);
- if (rData != NULL) UnlockBuffer (rBuffer);
-
- if (sBuffer != 0) FreeBuffer (sBuffer);
- if (dBuffer != 0) FreeBuffer (dBuffer);
- if (mBuffer != 0) FreeBuffer (mBuffer);
- if (rBuffer != 0) FreeBuffer (rBuffer);
-
- WriteScriptParams(globals);
-
- }